<template>
  <article class="page page-video2gif">
    <h4 class="text-center">视频转GIF</h4>
    <form class="form">
      <div class="form-group">
        <div class="alert alert-info">
          <div>1）本工具基于ffmpeg，需要先行安装ffmpeg。</div>
          <div>2）若操作执行失败，可尝试以管理员身份运行程序后重试。</div>
        </div>
      </div>
      <div class="form-group">
        <fieldset>
          <legend>视频数据</legend>
          <div class="form-group row">
            <div class="row-flex" align="center">
              <div class="row-flex-prefix">视频文件</div>
              <div class="row-flex-main"><input class="form-control" type="text" readonly v-model="fromPath" /></div>
              <div class="row-flex-suffix"><x-button @click="setFromPath">选择...</x-button></div>
            </div>
          </div>
          <div class="form-group row">
            <div class="col-6">
              <div class="row-flex" align="center">
                <div class="row-flex-prefix">总时长</div>
                <div class="row-flex-main text-grey">
                  <span>{{videoInfo.duration || '--'}}</span>
                </div>
              </div>
            </div>
            <div class="col-6">
              <div class="row-flex" align="center">
                <div class="row-flex-prefix">文件大小</div>
                <div class="row-flex-main text-grey">
                  <span>{{videoInfo.size || '--'}}</span>
                </div>
              </div>
            </div>
          </div>
          <div class="form-group row">
            <div class="col-6">
              <div class="row-flex" align="center">
                <div class="row-flex-prefix">宽高比</div>
                <div class="row-flex-main text-grey">
                  <span>{{videoInfo.aspect || '--'}}</span>
                </div>
              </div>
            </div>
          </div>
          <div class="form-group row">
            <div class="col-6">
              <div class="row-flex" align="center">
                <div class="row-flex-prefix">视频编码</div>
                <div class="row-flex-main text-grey">
                  <span>{{videoInfo.codec || '--'}}</span>
                </div>
              </div>
            </div>
            <div class="col-6">
              <div class="row-flex" align="center">
                <div class="row-flex-prefix">帧数/秒</div>
                <div class="row-flex-main text-grey">
                  <span>{{videoInfo.fps || '--'}}</span>
                </div>
              </div>
            </div>
          </div>
          <div class="form-group row">
            <div class="col-6">
              <div class="row-flex" align="center">
                <div class="row-flex-prefix">音频编码</div>
                <div class="row-flex-main text-grey">
                  <span>{{audioInfo.codec || '--'}}</span>
                </div>
              </div>
            </div>
            <div class="col-6">
              <div class="row-flex" align="center">
                <div class="row-flex-prefix">采样率</div>
                <div class="row-flex-main text-grey">
                  <span>{{audioInfo.sampleRate || '--'}}</span>
                </div>
              </div>
            </div>
          </div>
        </fieldset>
      </div>
      <div class="form-group">
        <fieldset>
          <legend>GIF设置</legend>
          <div class="form-group row">
            <div class="row-flex" align="center">
              <div class="row-flex-prefix">保存位置</div>
              <div class="row-flex-main"><input class="form-control" type="text" v-model="toPath" readonly /></div>
              <div class="row-flex-suffix"><x-button @click="setToPath">选择...</x-button></div>
            </div>
          </div>
          <div class="form-group row">
            <div class="col-6">
              <div class="row-flex" align="center">
                <label class="row-flex-prefix">开始时间</label>
                <div class="row-flex-main">
                  <input class="form-control" type="number" :min="0" :max="videoInfo.seconds - 1" v-model="startTime" />
                </div>
              </div>
            </div>
            <div class="col-6">
              <div class="row-flex" align="center">
                <label class="row-flex-prefix">截取时长</label>
                <div class="row-flex-main">
                  <input class="form-control" type="number" :min="1" :max="Math.floor(videoInfo.seconds)" v-model="duration" />
                </div>
                <div class="row-flex-suffix">秒</div>
              </div>
            </div>
          </div>
          <div class="form-group row">
            <div class="col-6">
              <div class="row-flex" align="center">
                <label class="row-flex-prefix">帧数/秒</label>
                <div class="row-flex-main"><input class="form-control" type="number" :min="1" :max="Math.floor(videoInfo.fps)" v-model="fps" /></div>
              </div>
            </div>
            <div class="col-6">
              <div class="row-flex" align="center">
                <label class="row-flex-prefix">文件名</label>
                <div class="row-flex-main"><input class="form-control" type="text" v-model.trim="fileName" /></div>
                <div class="row-flex-suffix">.gif</div>
              </div>
            </div>
          </div>
        </fieldset>
      </div>
      <div class="form-group text-center">
        <x-button type="primary" @click="resetData">重置</x-button>
        <x-button type="primary" @click="submitForm">开始转换</x-button>
      </div>
    </form>
  </article>
</template>

<script>
const fs = global.require('fs')
const path = global.require('path')
const {remote} = global.require('electron')
const {dialog} = remote
const selfWindow= remote.getCurrentWindow()
let ffmpeg = global.ffmpeg || null

export default {
  name: 'video2gif',
  data () {
    return {
      fromPath: '',
      toPath: this.$sharedObject('desktopPath'),
      fileName: '',
      fps: 1,
      startTime: 0,
      duration: 1,
      videoInfo: {duration: 0, seconds: 0, size: '', codec: '', fps: 0, aspect: ''},
      audioInfo: {codec: '', sampleRate: 0},
      videoProgress: null
    }
  },
  mounted () {
    ffmpeg = this.$sharedObject('ffmpeg')
  },
  methods: {
    resetData () {
      this.fromPath = ''
      this.toPath = this.$sharedObject('desktopPath')
      this.fileName = ''
      this.fps = 1
      this.startTime = 0
      this.duration = 1
      this.videoInfo = {duration: 0, seconds: 0, size: '', codec: '', fps: 0, aspect: ''}
      this.audioInfo = {codec: '', sampleRate: 0}
    },
    // 设置视频文件位置
    setFromPath () {
      let filePaths = dialog.showOpenDialogSync(selfWindow, {
        title: '选择文件',
        buttonLabel:'确定',
        defaultPath: this.$sharedObject('desktopPath'),
        properties: ['openFile']
      })
      if (filePaths instanceof Array && filePaths.length > 0) {
        this.resetData()
        this.fromPath = filePaths[0]
        this.getVideoInfo()
      }
    },
    // 设置保存位置
    setToPath () {
      let filePaths = dialog.showOpenDialogSync(selfWindow, {
        title: '选择目录',
        buttonLabel:'确定',
        defaultPath: this.$sharedObject('desktopPath'),
        properties: ['openDirectory']
      })
      if (filePaths instanceof Array && filePaths.length > 0) {
        this.toPath = filePaths[0]
      }
    },
    // 获取视频文件信息
    getVideoInfo () {
      let _this = this
      this.videoInfo = {duration: 0, seconds: 0, size: '', codec: '', fps: 0, aspect: ''}
      this.audioInfo = {codec: '', sampleRate: 0}
      fs.stat(this.fromPath, (err, data) => {
        if (err) {
          this.$toast(err)
          return
        }
        if (!data.isFile()) {
          this.$toast('文件不存在')
          return
        }
        this.$set(this.videoInfo, 'size', this.$jstools.formatFileSize(data.size))
        try {
          _this.videoProgress = new ffmpeg(_this.fromPath)
          _this.videoProgress.then(res => {
            let {duration, video, audio} = (res || {}).metadata || {}
            _this.$set(_this.videoInfo, 'duration', (duration || {}).raw)
            _this.$set(_this.videoInfo, 'seconds', (duration || {}).seconds)
            _this.$set(_this.videoInfo, 'codec', (video || {}).codec)
            _this.$set(_this.videoInfo, 'fps', (video || {}).fps)
            _this.$set(_this.videoInfo, 'aspect', ((video || {}).aspect || {}).string)
            _this.$set(_this.audioInfo, 'sampleRate', (audio || {}).sample_rate)
            _this.$set(_this.audioInfo, 'codec', (audio || {}).codec)
          }).catch(err => {
            _this.$toast(err)
          })
        } catch (err) {
          _this.$toast(err)
        }
      })
    },
    // 开始转换
    submitForm () {
      let _this = this
      if (!this.fileName) {
        this.$toast('请输入文件名称')
        return
      }
      if (this.startTime > Math.floor(this.duration - 1)) {
        this.$toast('开始时间必须小于视频时长')
        return
      }
      if (!this.toPath) {
        this.$toast('请选择保存位置')
        return
      }
      if (this.duration > (this.videoInfo.seconds - this.startTime)) {
        this.duration = Math.floor(this.videoInfo.seconds - this.startTime)
      }
      try {
        _this.videoProgress = _this.videoProgress || (new ffmpeg(_this.fromPath))
        _this.videoProgress.then(res => {
          let fp = path.join(_this.toPath, _this.fileName + '.gif')
          res
          .setVideoFrameRate(_this.fps)
          .setVideoStartTime(_this.startTime)
          .setVideoDuration(_this.duration)
          .save(fp, (err, file) => {
            if (err) {
              _this.$toast('保存文件失败:' + err)
            }
            _this.$toast('保存文件成功')
            console.log('submitForm:', err, file)
          })
        }).catch(err => {
          _this.$toast(err)
        })
      } catch (err) {
        _this.$toast(err)
      }
    },
  }
}
</script>

<style scoped lang="less">
@import "~@/assets/css/_mixins.less";
@import "~@/assets/css/_color.less";
.row-flex {
  & + .row-flex {
    margin-top: 1em;
  }
  .row-flex-prefix {
    width: 4.5em;
    text-align: right;
  }
  .row-flex-main {
    text-align: left;
  }
  .row-flex-suffix {
    min-width: 2em;
  }
}
.form-group {
  fieldset {
    height: 100%;
  }
  .x-button { width: 120px; }
}
</style>
